/** @file dataset.h
 *
 *  The generic dataset class.
 *
 *  @author Dongryeol Lee (drselee@gmail.com)
 */

#ifndef CORE_DATA_DATASET_H
#define CORE_DATA_DATASET_H

#include <armadillo>
#include <boost/mpi.hpp>
#include <string>
#include <vector>

#include "core/data/alias_vec.h"

namespace core {
namespace data {

class CSVParser;

class Dataset {

  private:

    friend class core::data::CSVParser;

  protected:

    std::vector< std::string > attribute_names_;

    double average_num_points_;

    std::vector< std::vector<std::string> > nominal_values_;

    arma::uvec raw_point_attribute_indices_;

    arma::uvec raw_target_attribute_indices_;

  protected:

    void FindPartition_(
      int file_length, int num_partitions, std::ifstream &is,
      bool attribute_header_present,
      std::vector <
      std::pair<int, int> > *partition_out);

    void SetupDefaultAttributeList_(int num_attributes_in);

  public:

    virtual ~Dataset();

    virtual double average_num_points() const = 0;

    virtual void Init(int num_attributes, int num_points) = 0;

    /** @brief Generates a random dataset containing a given number of
     *         points with the given dimensionality across all MPI
     *         processes.
     */
    void Init(
      boost::mpi::communicator &world, int num_attributes, int num_points);

    virtual void Init(
      boost::mpi::communicator &world,
      const std::string &file_name_in, bool from_single_file) = 0;

    virtual bool Init(const std::string &file_name_in) = 0;

    bool is_nominal_attribute(int attribute_index_in) const;

    int num_attributes() const;

    int num_point_attributes() const;

    virtual int num_points() const = 0;

    virtual void RandomGenerate(
      boost::mpi::communicator &world, int num_dimensions, int num_points) = 0;
};
}
}

#endif
